package team.seekers.hula.system.ratelimit.filter;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import team.seekers.hula.common.entity.UserSessionDTO;
import team.seekers.hula.common.utils.FilterUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;


/**
 * 用户限流过滤器，优先根据用户Id进行限流，其次根据IP+hash(UserAgent)进行限流，需要放置在 LoginFilter 后
 *
 * @author GH
 */
@Slf4j
@Component
public class UserLimitFilter extends GlobalLimitFilter {

    /**
     * Make sure that order is smaller than StripFilter‘s
     */
    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        Long userId = Optional.ofNullable(request.getHeader(UserSessionDTO.KEY_USERID_PREFIX))
                              .filter(StringUtils::isNumeric)
                              .map(Long::parseLong)
                              .orElse(null);
        String requestUrl = request.getRequestURI();
        String id;
        if (userId != null) {
            id = userId + "-" + requestUrl;
        } else {
            // 前置过滤器 LoginFilter 特意放行的请求
            String realIp = FilterUtils.getRealIp(request);
            String agent = Optional.ofNullable(request.getHeader("User-Agent")).orElse("");
            id = realIp + "-" + agent.hashCode() + "-" + requestUrl;
        }
        // 进行限流过滤
        super.rateFilter(request, response, chain, requestUrl, id, 1, super.filterProp.getUserLimitPaths());
    }
}
